package com.seadragon.app.ksr.controller;

import static com.seadragon.app.ksr.model.KsrConstants.ENTITY_TYPE_BUSINESS;
import static com.seadragon.app.ksr.model.KsrConstants.ENTITY_TYPE_CUSTOMER;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.seadragon.app.ksr.model.Business;
import com.seadragon.app.ksr.model.Customer;
import com.seadragon.app.ksr.model.FileMeta;
import com.seadragon.app.ksr.model.KsrConstants;
import com.seadragon.app.ksr.model.Office;
import com.seadragon.app.ksr.model.Picture;
import com.seadragon.app.ksr.service.CustomerService;
import com.seadragon.app.ksr.service.ImageService;
import com.seadragon.app.ksr.service.OfficeService;

@Controller
public class FileUploadController {
	private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);

	private LinkedList<FileMeta> files = new LinkedList<FileMeta>();
	private FileMeta fileMeta = null;

	@Value("${base.url}")
	private String baseUrl;

	@Autowired
	private CustomerService customerService;

	@Autowired
	private OfficeService officeService;

	@Autowired
	private ImageService imageService;

	@RequestMapping(value = "/{entityType}/upload.json", method = RequestMethod.POST)
	public @ResponseBody
	JSONObject upload(MultipartHttpServletRequest request, HttpServletResponse response, @PathVariable String entityType,
			@RequestParam(value = "entityId", required = true) String entityId) {

		// check if primary == fileName, the photo is primary

		// Find the office first
		JSONObject jsonObj = new JSONObject();

		if (entityId == null) {
			jsonObj.put("error", "The ID for office is null!");
			return jsonObj;
		}

		Office office = null;
		Customer customer = null;
		if (ENTITY_TYPE_BUSINESS.equalsIgnoreCase(entityType)) {
			office = officeService.findById(Long.parseLong(entityId));
			if (office == null) {
				jsonObj.put("error", "The ID for office is not valid : " + entityId);
				return jsonObj;
			}
		} else if (ENTITY_TYPE_CUSTOMER.equalsIgnoreCase(entityType)) {
			customer = customerService.findById(Long.parseLong(entityId));
			if (customer == null) {
				jsonObj.put("error", "The ID for customer is not valid : " + entityId);
				return jsonObj;
			}
		} else {
			jsonObj.put("error", "This entity type is not supported : " + entityType);
			return jsonObj;
		}
		// 1. build an iterator
		Iterator<String> itr = request.getFileNames();
		MultipartFile mpf = null;

		JSONArray jsonArray = new JSONArray();
		// 2. get each fileArray jsonArray = new JSONArray();
		while (itr.hasNext()) {
			// 2.1 get next MultipartFile
			mpf = request.getFile(itr.next());
			System.out.println(mpf.getOriginalFilename() + " uploaded! " + files.size());

			// 2.2 if files > 10 remove the first from the list
			if (files.size() >= 10)
				files.pop();

			// 2.3 create new fileMeta
			fileMeta = new FileMeta();
			fileMeta.setFileName(mpf.getOriginalFilename());
			fileMeta.setFileSize(mpf.getSize() / 1024 + " Kb");
			fileMeta.setFileType(mpf.getContentType());

			Picture picture = null;
			try {
				fileMeta.setBytes(mpf.getBytes());
				if (office != null) {
					picture = imageService.save(mpf.getBytes(), office);
				} else if (customer != null) {
					picture = imageService.save(mpf.getBytes(), customer);
				}

			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
			// 2.4 add to files
			files.add(fileMeta);
			jsonObj = new JSONObject();
			jsonObj.put("name", mpf.getOriginalFilename());
			jsonObj.put("size", mpf.getSize());
			jsonObj.put("url",
					baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getLargeImageFilename());
			jsonObj.put("thumbnailUrl",
					baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getMedianSquareImageFilename());
			if (office != null) {
				jsonObj.put("deleteUrl", "/ksr/" + entityType + "/" + office.getId() + "/" + picture.getPictureFolder() + "/"
						+ "delete-file.json");
				jsonObj.put("setPrimaryUrl", "/ksr/" + entityType + "/" + office.getId() + "/" + picture.getPictureFolder() + "/"
						+ "set-primary.json");
				jsonObj.put("entityId", office.getId());

			} else if (customer != null) {
				jsonObj.put("deleteUrl", "/ksr/" + entityType + "/" + customer.getId() + "/" + picture.getPictureFolder() + "/"
						+ "delete-file.json");
				jsonObj.put("setPrimaryUrl", "/ksr/" + entityType + "/" + customer.getId() + "/" + picture.getPictureFolder() + "/"
						+ "set-primary.json");
				jsonObj.put("entityId", customer.getId());
			}
			jsonObj.put("pictureFolder", picture.getPictureFolder());
			jsonObj.put("deleteType", "GET");
			jsonArray.add(jsonObj);
		}
		if (office != null) {
			office=officeService.update(office);
			updateSession(request.getSession(), office);
		} else if (customer != null) {
			customer=customerService.update(customer);
			updateSession(request.getSession(), customer);
		}
		jsonObj = new JSONObject();
		jsonObj.put("files", jsonArray);
		// result will be like this
		// [{"fileName":"app_engine-85x77.png","fileSize":"8 Kb","fileType":"image/png"},...]
		return jsonObj;
	}

	@RequestMapping(value = "/{entityType}/{entityId}/get-files.json", method = RequestMethod.GET)
	public @ResponseBody
	JSONObject getFiles(HttpServletRequest request, HttpServletResponse response, @PathVariable String entityType,
			@PathVariable long entityId) {
		JSONObject jsonObj = null;
		JSONArray jsonArray = new JSONArray();
		if (ENTITY_TYPE_BUSINESS.equals(entityType)) {
			Office office = officeService.findById(entityId);
			if (office != null && office.getPictures() != null && office.getPictures().size() > 0) {
				for (Picture picture : office.getPictures()) {
					jsonObj = buildFilesJson(picture, entityType, entityId);
					if (picture != null && office.getPrimaryPicture() != null && picture.getId() != 0
							&& office.getPrimaryPicture().getId() != 0 && picture.getId() == office.getPrimaryPicture().getId()) {
						jsonObj.put("primary", true);
					}
					jsonObj.put("entityId", office.getId());
					jsonObj.put("id", picture.getId());
					jsonArray.add(jsonObj);
				}
			}
		} else if (ENTITY_TYPE_CUSTOMER.equals(entityType)) {
			Customer customer = customerService.findById(entityId);
			if (customer != null && customer.getPictures() != null && customer.getPictures().size() > 0) {
				for (Picture picture : customer.getPictures()) {
					jsonObj = buildFilesJson(picture, entityType, entityId);
					if (picture != null && customer.getPrimaryPicture() != null && picture.getId() != 0
							&& customer.getPrimaryPicture().getId() != 0
							&& picture.getId() == customer.getPrimaryPicture().getId()) {
						jsonObj.put("primary", true);
					}
					jsonObj.put("id", picture.getId());
					jsonObj.put("entityId", customer.getId());
					jsonArray.add(jsonObj);
				}
			}
		}
		jsonObj = new JSONObject();
		jsonObj.put("files", jsonArray);
		return jsonObj;
	}

	private JSONObject buildFilesJson(Picture picture, String entityType, long entityId) {
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("pictureFolder", picture.getPictureFolder());
		jsonObj.put("url", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getLargeImageFilename());
		if (picture.getMedianImageFilename()!=null)
			jsonObj.put("medianImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getMedianImageFilename());
		if (picture.getLargeSquareImageFilename()!=null)
			jsonObj.put("largeSquareImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getLargeSquareImageFilename());
		if (picture.getMedianSquareImageFilename()!=null)
			jsonObj.put("medianSquareImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getMedianSquareImageFilename());
		if (picture.getSmallSquareImageFilename()!=null)
			jsonObj.put("smallSquareImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getSmallSquareImageFilename());
		if (picture.getExtraSmallSquareImageFilename()!=null)
			jsonObj.put("extraSmallSquareImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getExtraSmallSquareImageFilename());
		if (picture.getSquare90ImageFilename()!=null)
			jsonObj.put("square90ImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getSquare90ImageFilename());
		if (picture.getSquare60ImageFilename()!=null)
			jsonObj.put("square60ImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getSquare60ImageFilename());
		if (picture.getSquare30ImageFilename()!=null)
			jsonObj.put("square30ImageUrl", baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getSquare30ImageFilename());
		
		
		jsonObj.put("thumbnailUrl",
				baseUrl + picture.getRootPath() + picture.getPictureFolder() + File.separator + picture.getMedianSquareImageFilename());
		jsonObj.put("setPrimaryUrl", "/ksr/" + entityType + "/" + entityId + "/" + picture.getPictureFolder() + "/" + "set-primary.json");
		jsonObj.put("deleteUrl", "/ksr/" + entityType + "/" + entityId + "/" + picture.getPictureFolder() + "/" + "delete-file.json");
		jsonObj.put("deleteType", "GET");
		return jsonObj;
	}

	@RequestMapping(value = "/{entityType}/{entityId}/{directory}/delete-file.json", method = RequestMethod.GET)
	public @ResponseBody
	JSONObject deleteFile(HttpServletRequest request, HttpServletResponse response, @PathVariable String entityType,
			@PathVariable long entityId, @PathVariable String directory) {
		imageService.delete(entityType, entityId, directory);
		if ("business".equals(entityType)){
			updateSession(request.getSession(), officeService.findById(entityId));
		} else {
			updateSession(request.getSession(), customerService.findById(entityId));
		}
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("isDeleted", true);
		return jsonObj;
	}
	
	@RequestMapping(value = "/base-url/get.json", method = RequestMethod.GET)
	public @ResponseBody
	JSONObject getBaseUrl() {
		
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("baseUrl", this.baseUrl);
		return jsonObj;
	}
	
	@Deprecated
	@RequestMapping(value = "/get-base-url.json", method = RequestMethod.GET)
	public @ResponseBody
	JSONObject getBaseUrl1() {
		
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("baseUrl", this.baseUrl);
		return jsonObj;
	}

	@RequestMapping(value = "/{entityType}/{entityId}/{directory}/set-primary.json", method = RequestMethod.GET)
	public @ResponseBody
	JSONObject setPrimaryImage(HttpServletRequest request, HttpServletResponse response, @PathVariable String entityType,
			@PathVariable long entityId, @PathVariable String directory) {
		boolean setPrimary = false;
		if (ENTITY_TYPE_BUSINESS.equals(entityType)) {
			Office office = officeService.findById(entityId);
			if (office != null && office.getPictures() != null && office.getPictures().size() > 0) {
				for (Picture picture : office.getPictures()) {
					if (picture.getPictureFolder() != null && picture.getPictureFolder().equalsIgnoreCase(directory)) {
						office.setPrimaryPicture(picture);
						office = officeService.update(office);
						updateSession(request.getSession(), office);
						setPrimary = true;
						break;
					}
				}
			}
		} else if (ENTITY_TYPE_CUSTOMER.equals(entityType)) {
			Customer customer = customerService.findById(entityId);
			if (customer != null && customer.getPictures() != null && customer.getPictures().size() > 0) {
				for (Picture picture : customer.getPictures()) {
					if (picture.getPictureFolder() != null && picture.getPictureFolder().equalsIgnoreCase(directory)) {
						customer.setPrimaryPicture(picture);
						customer=customerService.update(customer);
						updateSession(request.getSession(), customer);
						setPrimary = true;
						break;
					}
				}
			}
		}
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("isSetPrimary", setPrimary);
		return jsonObj;
	}
	
	private void updateSession(HttpSession session, Object entity){
		if (entity instanceof Office){
			Office office = (Office)entity;
			int index=-1;
			Business businessInSession = (Business) (session.getAttribute(KsrConstants.SESSION_SCOPED_BUSINESS));
//			for (int i = 0; i < businessInSession.getOffices().size(); i++) {
//				if (businessInSession.getOffices().get(i).getId()==office.getId()){
//					index = i;
//					break; 
//				}
//				
//			}
//			
//			businessInSession.getOffices().set(index,office);
			session.setAttribute(KsrConstants.SESSION_SCOPED_BUSINESS, businessInSession);
		} else if (entity instanceof Customer){
			session.setAttribute(KsrConstants.SESSION_SCOPED_CUSTOMER, entity);
		}
	}
}